﻿using System;
using System.Collections.Generic;
using System.IO;
using Android.Content.PM;
using Android.Content.Res;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Support.Constraints;
using Android.Support.V4.App;
using Android.Util;
using Android.Views;
using Android.Views.Animations;
using Android.Widget;
using API;
using mb.DroidLib;
using Plugin.Permissions;
using Plugin.Permissions.Abstractions;
using Xamarin.Essentials;
using Xamarin.Forms.Platform.Android;
using Orientation = Android.Widget.Orientation;
using Permission = Plugin.Permissions.Abstractions.Permission;

namespace mb.Droid
{
    public class StartFragment : Android.Support.V4.App.Fragment, API.IUpdateNotify
    {
        static ILog logger = mb.ServiceLocator.Instance.Get<ILog>();
        static IStartOption startOption = ServiceLocator.Instance.Get<IStartOption>();

        ViewGroup rootLayout;
        ProgressBar updateProgressBar;
        TextView welcomeView;
        string updateGroup = "default";
        string updateUrl;
        bool isLoading;

        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            Activity.Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
            Activity.Window.SetStatusBarColor(Color.White);

            LitJson.JsonMapper.UnregisterExporters();
        }

        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            rootLayout = new RelativeLayout(this.Activity);
            rootLayout.SetBackgroundColor(Color.White);

            var imgLogo = new ImageView(this.Activity);
            imgLogo.SetImageResource(DroidLib.Resource.Drawable.mylogo);
            var lp = new RelativeLayout.LayoutParams(-2, -2)
            {
                // Width = 500,
            };
            lp.AddRule(LayoutRules.CenterInParent);
            rootLayout.AddView(imgLogo, lp);

            var bt = mb.AssemblyCreationDate.Value;
            var tv = new TextView(this.Activity)
            {
                Id = View.GenerateViewId(),
                Text = Xamarin.Essentials.AppInfo.VersionString + " @ " + bt.ToShortDateString() + ' ' + bt.ToShortTimeString()
            };
            tv.SetTextColor(Color.Black);
            tv.SetTextSize(ComplexUnitType.Dip, 14);
            rootLayout.AddView(tv, new RelativeLayout.LayoutParams(-2, -2)
                {
                    BottomMargin = 10
                }
                .AddRuleEx(LayoutRules.AlignParentBottom)
                .AddRuleEx(LayoutRules.CenterHorizontal));

            tv = new TextView(this.Activity)
            {
                Id = View.GenerateViewId(),
                Text = "配置加载中",
            };
            tv.SetTextColor(Color.Black);
            tv.SetTextSize(ComplexUnitType.Dip, 20);
            lp = new RelativeLayout.LayoutParams(-2, -2);
            lp.AddRule(LayoutRules.AlignParentBottom);
            lp.AddRule(LayoutRules.CenterHorizontal);
            lp.BottomMargin = 80;
            rootLayout.AddView(welcomeView = tv, lp);

            //progress
            rootLayout.AddView(
                updateProgressBar = new ProgressBar(this.Activity, null, Android.Resource.Style.WidgetProgressBarHorizontal)
                {
                    Max = 100,
                        ProgressDrawable = new ClipDrawable(new ColorDrawable(App.MainColor), GravityFlags.Left, ClipDrawableOrientation.Horizontal),
                        Visibility = ViewStates.Invisible,
                        Background = new ColorDrawable(App.MainBKColor),
                },
                new RelativeLayout.LayoutParams(600, 10) { BottomMargin = 50, }
                .AddRuleEx(LayoutRules.Above, welcomeView.Id)
                .AddRuleEx(LayoutRules.CenterHorizontal)
            );

            return rootLayout;
        }

        void AddMagicView()
        {
            var mv = new View(Activity) { Background = new ColorDrawable(Color.Argb(30, 0, 0, 0)), Alpha = 1 };
            mv.Click += delegate { ShowDevServers(); };
            rootLayout.AddView(mv,
                new RelativeLayout.LayoutParams(150, 150)
                .AddRuleEx(LayoutRules.AlignParentRight)
                .AddRuleEx(LayoutRules.AlignParentTop)
            );
        }

        public override void OnViewCreated(View view, Bundle savedInstanceState)
        {
            mb.Util.DoWhenTestFlag(() =>
            {
                //从await回来都要检查状态是否有效，因为已经时过境迁，本界面也许已卸载
                if (IsAdded)
                    AddMagicView();
            });

            StartAnimation();
            rootLayout.Click += delegate
            {
                if (isLoading) return;
                StartUpdate();
            };

            var autoServer = startOption.GetStringValue("autoserver");
            if (autoServer == "open")
            {
                ShowDevServers();
            }
            else if (autoServer != null)
            {
                var uri = App.AssetServerURI;
                var svInfo = autoServer.Split(":");
                var host = svInfo[0];
                var port = svInfo.Length == 2 ? int.Parse(svInfo[1]) : uri.Item2 - 10000;
                StartUpdate("test", host, port);
            }
            else
            {
                isLoading = true;
                App.AServerLoader = new ServerLoader();
                App.AServerLoader.StartLoad((rt, msg) =>
                {
                    Activity.RunOnUiThread(() =>
                    {
                        logger.Log("load-->", rt);
                        if (rt == ServerLoader.LoadResult.STEP_NOTIFY)
                        {
                            welcomeView.Text = "配置加载中:" + msg;
                        }
                        else if (rt == ServerLoader.LoadResult.NOT_AVAILABLE)
                        {
                            StopAnimation();
                            Util.ShowMsgBox(msg);
                        }
                        else if (rt == ServerLoader.LoadResult.NEED_UPDATE)
                        {
                            StopAnimation();
                            Util.ShowMsgBox("当前版本太低，请更新", onClick: () =>
                            {
                                logger.Log("click inside");
                                Xamarin.Essentials.Browser.OpenAsync(msg, BrowserLaunchMode.External);
                            });
                        }
                        else
                        {
                            // welcomeView.Text = "点击屏幕进入程序";
                            isLoading = false;

                            mb.Util.DoWhenTestFlag(
                                actYes: () =>
                                {
                                    welcomeView.Text = App.AssetServerURI.ToString();
                                    // mb.Droid.Util.ShowMsgBox($"当前服务器:{App.CurrentServerUrl}\n是否退出？", () => { });
                                },
                                actNo: () =>
                                {
                                    StartUpdate();
                                });
                        }
                    });
                });
            }
        }

        public override void OnStop()
        {
            base.OnStop();
        }

        void StopAnimation()
        {
            welcomeView.Animation?.Cancel();
            welcomeView.Animation?.SetAnimationListener(null);
            welcomeView.ClearAnimation();

        }
        void StartAnimation()
        {
            AlphaAnimation fadeIn = new AlphaAnimation(0, 1);
            AlphaAnimation fadeOut = new AlphaAnimation(1, 0);

            AnimationSet set = new AnimationSet(false);

            fadeOut.StartOffset = 500;
            set.AddAnimation(fadeIn);
            set.AddAnimation(fadeOut);
            set.Duration = fadeOut.StartOffset;
            set.AnimationEnd += (s, e) =>
            {
                welcomeView.StartAnimation(set);
            };
            welcomeView.StartAnimation(set);
        }

        void ShowDevServers()
        {
            new DevServerSelector()
            {
                OnSelect = (group, url, port) => StartUpdate(group, url, port),
            }.Show(FragmentManager, "dev");
        }

        void StartUpdate()
        {
            var activity = this.Activity as StartActivity;
            var uri = App.AssetServerURI;
            StartUpdate("default", uri.Item1, uri.Item2);
        }

        public void StartUpdate(string group, string url, int port)
        {
            StopAnimation();

            updateGroup = group;
            updateUrl = url;
            App.CurrentServerUrl = updateUrl + ":" + port;
            var updater = mb.ServiceLocator.Instance.Get<API.IAssetUpdater>();
            updater.SetFullUpdate(startOption.GetBoolValue("fullupdate"));
            updater.SetNotifyHandler(this);
            updater.StartUpdate(url, port);
        }

        void LoadHot()
        {
            var loader = ServiceLocator.Instance.Get<IHotLoader>();
            var dllPath = getStorageRoot() + $"/libmp.dll.android";
            var symPath = getStorageRoot() + $"/libmp.pdb.android";
            var dllData = File.ReadAllBytes(dllPath);
            var symData = File.ReadAllBytes(symPath);
            loader.Load(dllData, symData);
        }

        public void notifyBegin()
        {
            updateProgressBar.Visibility = ViewStates.Visible;
        }

        public void notifyDescription(string text)
        {
            welcomeView.Text = text;
        }

        public void notifyProgress(float percent)
        {
            updateProgressBar.Progress = (int) (percent * 100);
        }

        public void notifyEnd(bool succeed, string errMsg = "")
        {
            if (succeed)
            {
                var activity = this.Activity as StartActivity;
                App.HotStorageRoot = getStorageRoot();

                var resetBusinessServer = startOption.GetStringValue("resetBusinessServer");
                if (resetBusinessServer != null)
                    App.CurrentServerUrl = resetBusinessServer;

                LoadHot();
            }
            else
            {
                notifyDescription(errMsg);
            }
        }

        public bool isFileNeed(string path)
        {
            return true;
        }

        public bool shouldFileRemove(string path)
        {
            return true;
        }

        public string getStorageRoot()
        {
            return Xamarin.Essentials.FileSystem.CacheDirectory + "/hotupdate/" + updateGroup;
        }
    }

    public class DevServerSelector : Android.Support.V4.App.DialogFragment
    {
        static ILog logger = mb.ServiceLocator.Instance.Get<ILog>();
        IServerProber serverProber;
        Dictionary < string, (string url, int port) > servers = new Dictionary < string, (string, int) > ();
        ArrayAdapter listAdapter;
        public Action<string, string, int> OnSelect;

        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            serverProber = mb.ServiceLocator.Instance.Get<IServerProber>();
            serverProber.SetPort(App.AssetServerURI.Item2 + 1);
            serverProber.Refresh();
            serverProber.onNewServer += (name, ip, port) =>
            {
                logger.Log("found server", name, ip, port);
                Activity?.RunOnUiThread(() =>
                {
                    if (servers.ContainsKey(name)) return;
                    servers.Add(name, (ip, port));
                    listAdapter.Add(name);
                    listAdapter.NotifyDataSetChanged();
                });
            };

            listAdapter = new ArrayAdapter(Context, DroidLib.Resource.Layout.item_my_item);
        }

        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {

            var win = Dialog.Window;
            Dialog.SetTitle("请选择服务器");
            logger.Log("win", win.GetHashCode(), Activity.Window.GetHashCode());

            var layout = new LinearLayout(Context);
            layout.Orientation = Orientation.Vertical;
            layout.LayoutParameters = new ViewGroup.LayoutParams(-1, -1);

            var list = new ListView(Context);
            list.Adapter = listAdapter;
            list.ItemClick += (s, e) =>
            {
                logger.Log("click item", e.Position);
                this.Dismiss();
                var name = listAdapter.GetItem(e.Position).ToString();
                var server = servers[name];
                var nameGroup = name.Split(":");
                var group = nameGroup.Length > 1 ? nameGroup[0] : "test";
                OnSelect?.Invoke(group, server.url, server.port);

            };
            layout.AddView(list, new LinearLayout.LayoutParams(-1, 1000));

            return layout;
        }

        public override void OnStart()
        {
            base.OnStart();

            var win = Dialog.Window;
            // win.SetLayout(-1, 600);
        }

        public override void OnStop()
        {
            base.OnStop();
        }
    }
}